﻿using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using FTI.Core;
using System.Data;
using System.Diagnostics;

namespace FTI.Testing
{
    /// <summary>
    /// Summary description for CSVFileReaderTest
    /// </summary>
    [TestClass]
    public class CSVFileReaderTest
    {
        public CSVFileReaderTest()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        internal class Columns
        {
            public const string Date = "Date";
            public const string Int32 = "Int32";
            public const string String = "String";
            public const string Decimal = "Decimal";
        }

        #region CSV Data Row Test Strings
        const string LINE1 = "\"6/13/2015\",1,\"Line Item One\",3.25\r\n";
        const string LINE2 = "\"6/13/2015\",2,\"Line Item One\",3.25,\"\"\r\n";
        const string LINE3 = "6/13/2015,3,\"Line Item \"\"Three\"\"\",3.25\r\n";
        const string LINE4 = "\"July 13, 2015\",4,\"Line Item \"\"Four\"\"\",3.25\r\n";
        const string LINE5 = "\"\",5,\"Line Item \"\"Five\"\"\",63.25\r\n";
        const string LINE6 = "\"6/14/2015\",,,73.25\r\n";
        const string LINE7 = "\"6/14/2015\",7,\"Line Item \"\"Seven\"\"\",\r\n";
        #endregion

        private DataTable Table
        {
            get
            {
                DataTable oTable = new DataTable();

                oTable.Columns.Add(new DataColumn(Columns.Date, typeof(DateTime)));
                oTable.Columns.Add(new DataColumn(Columns.Int32, typeof(Int32)) { AllowDBNull = true });
                oTable.Columns.Add(new DataColumn(Columns.String, typeof(String)) { AllowDBNull = false });
                oTable.Columns.Add(new DataColumn(Columns.Decimal, typeof(Decimal)) { AllowDBNull = true });

                return oTable;
            }
        }

        [TestMethod]
        public void ParseCSVTestLines()
        {
            using (MemoryStream oData = new MemoryStream(Encoding.UTF8.GetBytes(LINE1 + LINE2 + LINE3 + LINE4 + LINE5 + LINE6 + LINE7)))
            using (CSVFileReader oReader = new CSVFileReader(oData, Encoding.UTF8))
            {
                int count = 0;

                oReader.Table = Table;

                count++;

                object[] oLineData = oReader.MapLineToDataRow(LINE1, count);

                for (int x = 0; x < Table.Columns.Count; x++)
                {
                    Assert.IsTrue(oLineData[x].GetType() == Table.Columns[x].DataType, String.Format("Failed to map data to column {0}", Table.Columns[x].ColumnName));
                }

                count++;

                DataTable oTable = new DataTable();

                oTable.Columns.AddRange(new DataColumn[]
                {
                    new DataColumn(Columns.Date, typeof(DateTime)),
                    new DataColumn(Columns.Int32, typeof(Int32)) { AllowDBNull = true },
                    new DataColumn(Columns.String, typeof(String)) { AllowDBNull = false },
                    new DataColumn(Columns.Decimal, typeof(Decimal))
                });

                if (!oReader.Read(ref oTable))
                {
                    Assert.IsNotNull(oReader.Errors);

                    Trace.Write(oReader.Errors);
                }
                else
                {
                    Assert.Fail("Errors should have been detected.");
                }
            }
        }

        [TestMethod]
        public void ShouldSucceedAtCsvImport()
        {
            using (MemoryStream oData = new MemoryStream(Encoding.UTF8.GetBytes(LINE1 + LINE3 + LINE4 + LINE7)))
            using (CSVFileReader oReader = new CSVFileReader(oData, Encoding.UTF8))
            {
                DataTable oTable = new DataTable();

                oTable.Columns.AddRange(new DataColumn[]
                {
                    new DataColumn(Columns.Date, typeof(DateTime)),
                    new DataColumn(Columns.Int32, typeof(Int32)),
                    new DataColumn(Columns.String, typeof(String)),
                    new DataColumn(Columns.Decimal, typeof(Decimal))
                });

                Assert.IsTrue(oReader.Read(ref oTable), "Errors encountered where there should be none.");

                Trace.Write(oReader.Errors);
            }
        }
    }
}
